package templateExecel2.utils;

import lombok.Getter;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StringUtils {

    private static Pattern DOUBLE_QUOTES_PATTEN = Pattern.compile("\"[^\"]*\"");
    private static Pattern SINGLE_QUOTES_PATTEN = Pattern.compile("'[^']*'");

    public static StringRecover extract(String s) {
        Stack<String> strings = new Stack<>();

        //名称和字符串内容
        Map<String, String> nameString = new HashMap<>();

        //替换所有被转译的字符串
        s = s.replaceAll("\\\\'", "____SINGLE_QUOTES_SYMBOL____");
        s = s.replaceAll("\\\\\"", "____DOUBLE_QUOTES_SYMBOL____");

        StringBuilder builder = new StringBuilder();

        int end = 0;

        //单引号字符串

        Matcher sqpm = SINGLE_QUOTES_PATTEN.matcher(s);

        int sn = 0;

        while (sqpm.find()) {
            String name = "_____STRING_NAME_" + (sn++);
            String st = sqpm.group();
            //放入字符串
            nameString.put(name, st);
            //压入栈中
            strings.push(name);

            builder.append(s, end, sqpm.start()).append(name);
            end = sqpm.end();
        }
        builder.append(s.substring(end));

        //更新字符串
        s = builder.toString();
        builder.delete(0, builder.length());


        Matcher dqpm = DOUBLE_QUOTES_PATTEN.matcher(s);
        end = 0;
        while (dqpm.find()) {
            String name = "_____STRING_NAME_" + (sn++);
            String st = dqpm.group();
            //放入字符串
            nameString.put(name, st);
            //压入栈中
            strings.push(name);

            builder.append(s, end, dqpm.start()).append(name);
            end = dqpm.end();
        }
        builder.append(s.substring(end));

        s = builder.toString();
        builder.delete(0, builder.length());
        //------字符串保护------

        StringRecover recover = new StringRecover();
        recover.result = s;
        recover.nameString = nameString;
        recover.strings = strings;
        return recover;

    }

    public static class StringRecover {
        private List<String> strings = new Stack<>();
        private Map<String, String> nameString = new HashMap<>();
        private String result;

        public String getResult() {
            return result;
        }

        //恢复字符串
        public String recover(String s) {

            if (strings.size() > 0) {
                //倒序遍历替换所有字符串
                for (int i = strings.size() - 1; i >= 0; i--) {
                    String name = strings.get(i);
                    String st = nameString.get(name);
                    s = s.replace(name, st);
                }
            }
            s = s.replace("____SINGLE_QUOTES_SYMBOL____", "\\\'");
            s = s.replace("____DOUBLE_QUOTES_SYMBOL____", "\\\"");
            return s;
        }

    }


    /**
     * @param string 被查找的串
     * @param from   开始位置
     * @param pre    前置符号
     * @param post   后置符号
     * @param number 成对出现的次数
     * @return
     */
    public static SubStringResult pairingSubString(String string, int from, char pre, char post) {


        if (string == null) {
            return null;
        }


        char[] chars = string.toCharArray();
        if (from < 0 || from >= chars.length) {
            return null;
        }
        StringBuilder builder = new StringBuilder();

        //个数
        int preNumber = 0;
        int n = 0;

        int start = 0;

        for (int i = from; i < chars.length; i++) {
            char c = chars[i];
            if (c == pre) {
                if (preNumber == 0) {
                    start = i;
                }
                preNumber++;
            } else if (c == post) {
                preNumber--;
                if (preNumber < 0) {
                    return null;
                } else if (preNumber == 0) {
                    n++;
                    if (n == 1) {
                        builder.append(c);
                        SubStringResult subStringResult = new SubStringResult();
                        subStringResult.start = start;
                        subStringResult.end = i + 1;
                        subStringResult.subString = builder.toString();
                        subStringResult.from = from;

                        return subStringResult;
                    }
                }
            }
            if (preNumber > 0) {
                builder.append(c);
            }
        }

        return null;

    }

    public static SubStringResult pairingSubStringReverse(String string, int from, char pre, char post) {

        if (string == null) {
            return null;
        }

        char[] chars = string.toCharArray();

        if (from < 0 || from >= chars.length) {
            return null;
        }

        StringBuilder builder = new StringBuilder();

        //个数
        int preNumber = 0;
        int n = 0;

        int end = 0;

        for (int i = from; i >= 0; i--) {
            char c = chars[i];
            if (c == pre) {
                if (preNumber == 0) {
                    end = i + 1;
                }
                preNumber++;
            } else if (c == post) {
                preNumber--;
                if (preNumber < 0) {
                    return null;
                } else if (preNumber == 0) {
                    n++;
                    if (n == 1) {
                        builder.append(c);
                        SubStringResult subStringResult = new SubStringResult();
                        subStringResult.end = end;
                        subStringResult.start = i;
                        subStringResult.subString = builder.reverse().toString();
                        subStringResult.from = from;

                        return subStringResult;
                    }
                }
            }
            if (preNumber > 0) {
                builder.append(c);
            }
        }

        return null;

    }


    //拒绝字符
    public static SubStringResult rejectCharSubStringReverse(String string, int from, char... chars) {
        if (string == null) {
            return null;
        }
        if (chars.length == 0) {
            return null;
        }
        Set<Character> characters = new HashSet<>();
        for (char aChar : chars) {
            characters.add(aChar);
        }
        char[] array = string.toCharArray();
        if (from < 0 || from >= array.length) {
            return null;
        }
        int i;
        StringBuilder builder = new StringBuilder();
        for (i = from; i >= 0; i--) {
            if (characters.contains(array[i])) {
                break;
            }
            builder.append(array[i]);
        }

        SubStringResult result = new SubStringResult();
        result.start = i + 1;
        result.end = from + 1;
        result.subString = builder.reverse().toString();
        result.from = from;

        return result;
    }

    public static SubStringResult findCharSubString(String string, int from, char... chars) {
        if (string == null) {
            return null;
        }
        if (chars.length == 0) {
            return null;
        }
        Set<Character> characters = new HashSet<>();
        for (char aChar : chars) {
            characters.add(aChar);
        }
        char[] array = string.toCharArray();

        if (from < 0 || from >= array.length) {
            return null;
        }

        int i;
        StringBuilder builder = new StringBuilder();
        for (i = from; i < array.length; i++) {
            if (characters.contains(array[i])) {
                break;
            }
            builder.append(array[i]);
        }

        SubStringResult result = new SubStringResult();
        result.start = from;
        result.end = i;
        result.subString = builder.toString();
        result.from = from;
        return result;
    }

    @Getter
    public static class SubStringResult {
        private String subString;
        private int start;
        private int end;
        private int from;

        //末尾指针是否等于from (末尾指针应该使用)
        public boolean endEqualsFrom() {
            return end == from + 1;
        }

        //开始指针是否等于from
        public boolean startEqualsFrom() {
            return from == from;
        }

        public boolean empty() {
            return start == end;
        }

    }

}
